Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Pytest CI mode to optimise migrations #3815

Merged
merged 6 commits into from
Apr 24, 2024
Merged

Conversation

khvn26
Copy link
Member

@khvn26 khvn26 commented Apr 20, 2024

Thanks for submitting a PR! Please check the boxes below:

  • I have run pre-commit to check linting
  • I have added information to docs/ if required so people know about the feature!
  • I have filled in the "Changes" section below?
  • I have filled in the "How did you test this code" section below?
  • I have used a Conventional Commit title for this Pull Request

Changes

This PR introduces a "CI mode" to Core API test runner, invoked by providing the --ci option to pytest.

In this mode, the following optimisations are applied to how pytest manages Django databases when in xdist mode:

  • Databases for workers are created using Django's native cloning method. This means that the migrations are run only once, and all the subsequent databases are copied using CREATE DATABASE ... WITH TEMPLATE query.
  • Database setup is only run on the controller node outside of the test session.
  • Database teardown is completely skipped.

Locally, this yields a substantial decrease in overall running time:

make test  708.02s user 34.22s system 216% cpu 5:43.19 total
make test opts='--ci'  558.61s user 29.81s system 255% cpu 3:50.14 total

I suspect it won't be as prominent in CI as it probably improves linearly with the number of workers (which is going to be less in CI).

How did you test this code?

The only proper way was to run the whole test suite.

Copy link

vercel bot commented Apr 20, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 24, 2024 0:58am
flagsmith-frontend-preview ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 24, 2024 0:58am
flagsmith-frontend-staging ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 24, 2024 0:58am

Copy link
Contributor

github-actions bot commented Apr 20, 2024

Uffizzi Preview deployment-50530 was deleted.

@codecov-commenter
Copy link

codecov-commenter commented Apr 20, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 95.92%. Comparing base (f9ec0b6) to head (15ba6ab).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3815   +/-   ##
=======================================
  Coverage   95.91%   95.92%           
=======================================
  Files        1122     1122           
  Lines       35482    35501   +19     
=======================================
+ Hits        34034    34053   +19     
  Misses       1448     1448           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@zachaysan zachaysan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved with some suggestions and questions, but overall looks useful 👍🏼

def pytest_configure(config: pytest.Config) -> None:
if (
config.option.ci
and config.option.dist != "no"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised that the option's value comes out as "no" instead of False.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"no" is, in fact, one of xdist's distribution modes. See here.

if (
config.option.ci
and config.option.dist != "no"
and not hasattr(config, "workerinput")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems weird that if ci is present that if workerinput is set that this will silently fail. Don't we prefer an exception if ci is set and so is workerinput?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having ci and having workerinput is a legitimate case when we need this hook to be a noop.

Comment on lines +70 to +74

def pytest_addoption(parser: pytest.Parser) -> None:
parser.addoption(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just confirming that this function will be auto-invoked without a decorator.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See coverage report :)

Dive into pytest hooks if you're curious about how this works.

def django_db_setup(request: pytest.FixtureRequest) -> None:
if (
request.config.option.ci
and (xdist_worker_id_suffix := get_xdist_worker_id(request)[2:]).isnumeric()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not obvious why

get_xdist_worker_id(request)[2:]

That part of the logic ends with a [2:]. Can you add a comment?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

@khvn26 khvn26 added this pull request to the merge queue Apr 24, 2024
Merged via the queue into main with commit 25afe3b Apr 24, 2024
19 of 22 checks passed
@khvn26 khvn26 deleted the feat/pytest-migrate-once branch April 24, 2024 12:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api Issue related to the REST API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants